package kr.co.insoft.core.service.configration.sev.impl;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import kr.co.insoft.core.model.configration.sev.SEVMetadataEntityModel;
import kr.co.insoft.framework.exceptions.ExceptionCode;
import kr.co.insoft.framework.exceptions.ServiceException;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.Predicate;

public class SEVCompute {

	final List<SEVMetadataEntityModel> metadatas;
	
	public SEVCompute(List<SEVMetadataEntityModel> metadatas) {
		this.metadatas = metadatas;
	}
	
	public List<SEVMetadataEntityModel> getVariablesAsTable()
			throws ServiceException {
		try {
			List<SEVMetadataEntityModel> result = new ArrayList<SEVMetadataEntityModel>();
			if ( metadatas != null && metadatas.size() > 0 ) {
				Set<Integer> groupRowItem = new HashSet<Integer>();
				for (SEVMetadataEntityModel sev : metadatas) {
					if (sev.getArrayRow() != -1)
						groupRowItem.add(sev.getArrayRow());
				}

				for (SEVMetadataEntityModel sev : metadatas) {
					if (!sev.getArray()) {
						result.add(sev);
					}
				}

				SEVMetadataEntityModel sevMetadataEntityModel = null;
				for (int findArrayItems : groupRowItem) {
					sevMetadataEntityModel = new SEVMetadataEntityModel();
					sevMetadataEntityModel
							.setArrays(new ArrayList<ArrayList<SEVMetadataEntityModel>>());
					List<SEVMetadataEntityModel> arrays = selectTr(metadatas,
							findArrayItems);
					Set<Integer> rows = new HashSet<Integer>();
					for (SEVMetadataEntityModel row : arrays) {
						sevMetadataEntityModel.setSeq(row.getSeq());
						sevMetadataEntityModel.setTitle(row.getTitle());
						sevMetadataEntityModel.setRefUserTypeId(row
								.getRefUserTypeId());
						rows.add(row.getRows());
					}

					for (int row : rows) {
						sevMetadataEntityModel.addArray(groupingTr(metadatas,
								findArrayItems, row));
					}
					sevMetadataEntityModel.setArrayRow(findArrayItems);
					sevMetadataEntityModel.setArray(true);
					result.add(sevMetadataEntityModel);
				}

				Collections.sort(result, new SEVMetadataComparator());
			}
			return result;
		} catch (Exception e) {
			throw new ServiceException(ExceptionCode.SERVICE_EXCEPTION, e);
		}
	}
	
	@SuppressWarnings("unchecked")
	private ArrayList<SEVMetadataEntityModel> groupingTr(
			final List<SEVMetadataEntityModel> metadatas,
			final int findArrayRow, final int rows) {
		return (ArrayList<SEVMetadataEntityModel>) CollectionUtils.select(
				metadatas, new Predicate() {
					@Override
					public boolean evaluate(Object meta) {
						SEVMetadataEntityModel sev = (SEVMetadataEntityModel) meta;
						return sev.getArray()
								&& sev.getArrayRow() == findArrayRow
								&& sev.getRows() == rows;
					}
				});
	}

	@SuppressWarnings("unchecked")
	private List<SEVMetadataEntityModel> selectTr(
			final List<SEVMetadataEntityModel> metadatas, final int findArrayRow) {
		return (List<SEVMetadataEntityModel>) CollectionUtils.select(metadatas,
				new Predicate() {
					@Override
					public boolean evaluate(Object meta) {
						return ((SEVMetadataEntityModel) meta).getArray()
								&& ((SEVMetadataEntityModel) meta)
										.getArrayRow() == findArrayRow;
					}
				});
	}
}
